/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel.database.engine;

import cn.webwheel.ObjectFactory;
import cn.webwheel.database.ConnectionProvider;
import cn.webwheel.database.IException;
import cn.webwheel.database.IPool;
import cn.webwheel.database.UserType;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * IPool factory class.
 */
public class IPoolFactory {

    Map<Class, Class<? extends IPoolObject>> iclsmap = new ConcurrentHashMap<Class, Class<? extends IPoolObject>>();

    Map<String, UserTypeInfo> userTypeInfoMap = new HashMap<String, UserTypeInfo>();

    /**
     * user type for result fetching
     * @param name name of user type
     * @param bCls bean class
     * @param dCls database class
     * @param userType user type
     */
    public <B, D> void addUserType(String name, Class<B> bCls, Class<D> dCls, UserType<? extends B, D> userType) {
        if (name == null) {
            userTypeInfoMap.remove(name);
            return;
        }
        if (userType == null) throw new IllegalArgumentException("userType is null");
        if (bCls == null) throw new IllegalArgumentException("bCls is null");
        if (dCls == null) throw new IllegalArgumentException("dCls is null");
        if(!Utils.isBasicType(dCls)) throw new IllegalArgumentException("dCls is not basic type for database");
        UserTypeInfo uti = new UserTypeInfo();
        uti.userType = userType;
        uti.bCls = bCls;
        uti.dCls = dCls;
        userTypeInfoMap.put(name, uti);
    }

    /**
     * factory method.<br/>
     * use no translators
     * @param conProvider database connection factory object
     * @param objectFactory object factory object
     * @return IPool
     */
    public IPool create(ConnectionProvider conProvider, ObjectFactory objectFactory) {
        return new IPoolImpl(this, conProvider, objectFactory);
    }

    /**
     * factory method.<br/>
     * use default object factory: Class.newInstance()<br/>
     * use no translators
     * @param conProvider database connection factory object
     * @return IPool
     */
    public IPool create(ConnectionProvider conProvider) {
        return create(conProvider, new ObjectFactory() {
            public <T> T getInstanceOf(Class<T> cls) {
                try {
                    return cls.newInstance();
                } catch (Exception e) {
                    throw new IException("can not create instance of " + cls, e);
                }
            }
        });
    }
}
